package com.witdata.common.service.impl;

import com.mybatisflex.core.query.QueryWrapper;
import com.witdata.mysql.base.service.PermBaseService;
import com.witdata.mysql.base.service.RolePermBaseService;
import com.witdata.mysql.base.service.UserPermBaseService;
import com.witdata.common.domain.Status;
import com.witdata.common.domain.dto.PermDto;
import com.witdata.mysql.domain.entity.TPerm;
import com.witdata.mysql.domain.entity.TRolePerm;
import com.witdata.mysql.domain.entity.TUserPerm;
import com.witdata.common.exception.GlobalException;
import com.witdata.common.mapper.PermMapper;
import com.witdata.common.util.SnowflakeUtils;
import com.witdata.common.service.PermService;
import com.witdata.common.service.RoleService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import jakarta.servlet.http.HttpServletRequest;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
@RequiredArgsConstructor
@Lazy
public class PermServiceImpl implements PermService {

    private final PermBaseService permBaseService;
    private final UserPermBaseService userPermBaseService;
    private RoleService roleService;
    private final RolePermBaseService rolePermBaseService;
    private final HttpServletRequest request;
    private SnowflakeUtils snowflakeUtils;

    @Override
    public List<String> getPermCodeListByUserId(Long userId) {
        List<String> permList = new ArrayList<>();
        List<TUserPerm> tUserPermList = userPermBaseService.list(new QueryWrapper().eq("user_id", userId));
        if (!CollectionUtils.isEmpty(tUserPermList)) {
            List<Long> permIdList = tUserPermList.stream().map(TUserPerm::getPermId).toList();
            List<TPerm> tPermList = permBaseService.listByIds(permIdList);
            if (!CollectionUtils.isEmpty(tPermList)) {
                permList.addAll(tPermList.stream().map(TPerm::getCode).toList());
            }
        }
        List<Long> roleIdList = roleService.getRoleIdListByUserId(userId);
        if (!CollectionUtils.isEmpty(roleIdList)) {
            List<String> permCodeList = getPermListByRoleIdList(roleIdList);
            permList.addAll(permCodeList);
        }
        return permList;
    }

    @Override
    public List<String> getPermListByRoleIdList(List<Long> roleIdList) {
        List<TRolePerm> tRolePermList = rolePermBaseService.list(new QueryWrapper().in("role_id", roleIdList));
        if (CollectionUtils.isEmpty(tRolePermList)) return List.of();
        List<Long> permIdList = tRolePermList.stream().map(TRolePerm::getPermId).toList();
        List<TPerm> tPermList = permBaseService.listByIds(permIdList);
        if (CollectionUtils.isEmpty(tPermList)) return List.of();
        return tPermList.stream().map(TPerm::getCode).toList();
    }

    @Override
    public Set<String> getPermCodeSetByUserId(Long userId) {
        List<String> permList = getPermCodeListByUserId(userId);
        return new HashSet<>(permList);
    }

    @Override
    public void savePerm(PermDto permDto) {
        boolean exists = permBaseService.exists(new QueryWrapper().eq("name", permDto.getName()));
        if (exists) throw new GlobalException(Status.PERMALREADYEXISTS);
        Long userId = (Long) request.getAttribute("userId");
        TPerm tPerm = PermMapper.INSTANCE.toTPerm(permDto);
        long id = snowflakeUtils.nextId();
        tPerm.setId(id);
        tPerm.setCreateTime(LocalDateTime.now());
        // 设置创建者
        tPerm.setCreateBy(userId);
        permBaseService.save(tPerm);
    }

    @Override
    public List<PermDto> getPermList() {
        List<TPerm> tPermList = permBaseService.list();
        return PermMapper.INSTANCE.toPermDtoList(tPermList);
    }


    @Autowired
    @Lazy
    public void setRoleService(RoleService roleService) {
        this.roleService = roleService;
    }

    @Autowired
    public void setSnowflakeUtils(SnowflakeUtils snowflakeUtils) {
        this.snowflakeUtils = snowflakeUtils;
    }
}
